Skip to content

feat(highlights): position-based text highlighting#340

Draft
kdroidFilter wants to merge 1 commit intomasterfrom
feat/position-based-highlights
Draft

feat(highlights): position-based text highlighting#340
kdroidFilter wants to merge 1 commit intomasterfrom
feat/position-based-highlights

Conversation

@kdroidFilter
Copy link
Owner

@kdroidFilter kdroidFilter commented Feb 2, 2026

Summary

  • Replace text-matching highlight system with position-based approach
  • Highlights now stored with lineId + character offsets instead of matching text
  • Only the specific selected instance is highlighted, not all occurrences of the same text
  • Add LineTextRegistry to track visible line content for position lookup
  • Use deterministic iteration (sorted by lineId) for consistent behavior

Technical Details

  • HighlightStore.kt: Refactored to store UserHighlight(lineId, startOffset, endOffset, color)
  • LineTextRegistry.kt: New registry tracking plain text of visible lines per tab
  • Highlighting.kt: Updated applyUserHighlights to use position offsets
  • BookContentView.kt: Filter highlights per line, register line text with registry
  • BookContentScreen.kt: Use registry to find position when adding highlights

Note

Highlights are currently in-memory only and will be lost when the app closes.

Follow-up: Persistence Implementation

To persist highlights to UserSettingsDb, the following changes are needed:

1. Create UserHighlights.sq

Location: SeforimApp/src/commonMain/sqldelight/io/github/kdroidfilter/seforimapp/db/

CREATE TABLE IF NOT EXISTS user_highlights (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    bookId INTEGER NOT NULL,
    lineId INTEGER NOT NULL,
    startOffset INTEGER NOT NULL,
    endOffset INTEGER NOT NULL,
    colorArgb INTEGER NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_highlights_book ON user_highlights(bookId);

selectAllForBook:
SELECT * FROM user_highlights WHERE bookId = ?;

insert:
INSERT INTO user_highlights(bookId, lineId, startOffset, endOffset, colorArgb)
VALUES (?, ?, ?, ?, ?);

deleteOverlapping:
DELETE FROM user_highlights 
WHERE bookId = ? AND lineId = ? 
AND startOffset < ? AND endOffset > ?;

deleteForBook:
DELETE FROM user_highlights WHERE bookId = ?;

2. Create HighlightRepository.kt

Follow the pattern of CategoryDisplaySettingsStore:

  • Inject UserSettingsDb
  • Async methods for CRUD operations
  • Convert ColorInt (using color.toArgb() and Color(argb))

3. Modify HighlightStore.kt

  • Inject HighlightRepository
  • Load highlights from DB on first access per book
  • Persist changes in addHighlight() / removeHighlight()
  • Keep in-memory cache for reactive UI updates

Test plan

  • Select text and apply highlight color from context menu
  • Verify only the selected instance is highlighted, not all occurrences
  • Test with text that appears multiple times in the document
  • Verify highlight removal works correctly

@kdroidFilter kdroidFilter marked this pull request as draft February 2, 2026 14:00
@kdroidFilter kdroidFilter force-pushed the feat/position-based-highlights branch 6 times, most recently from d1e0ed4 to b5e14a5 Compare February 2, 2026 20:57
- Add character offset tracking for precise highlight positioning
- Preserve highlight position when toggling nikud/taamim visibility
- Improve highlight color picker UI in context menu
- Use proper menu item colors for icons and text
@kdroidFilter kdroidFilter force-pushed the feat/position-based-highlights branch from c88c85f to ae66dda Compare February 2, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant